//
// Created by 11478 on 2024/7/4.
//

#ifndef SFUDP_UDP_H
#define SFUDP_UDP_H

#include <string>
#include <iostream>
#include <cstring>
#include <arpa/inet.h>
#include <sys/socket.h>
#include <vector>
#include <unistd.h>
#include <typeinfo>
#include <stdlib.h>
#include <thread>
#include <functional>
#include <memory>

class UDP {
public:
    UDP(int port, std::function<void(const char *, int, int)> recvFunction);

    ~UDP();

    void start();

private:
    void receive();

    int sockfd;
    int port;
    bool stop;
    struct sockaddr_in servaddr;
    std::thread receiverThread;
    std::function<void(const char *, int, int)> recvFunction;
};

class UDPSender {
public:
    UDPSender(const std::string &address, int port);

    ~UDPSender();

    void send(const std::vector<char> &message);

private:
    int sockfd;
    struct sockaddr_in destAddr;
};

class UDPManager {
public:
    static const int BASE_PORT = 12300;

    static const int BUFFER_SIZE = 1024;

    void addUDP(int port, std::function<void(const char *, int, int)> recvFunction);

    void addSender(const std::string &address, int port);

    void sendToAll(std::vector<char> &message);

    void startAll();

private:

    std::vector <std::unique_ptr<UDP>> udps;

    std::vector <std::unique_ptr<UDPSender>> senders;
};

#endif //SFUDP_UDP_H
